package com.mask.token.autoconfigure;

import com.mask.token.config.MaskTokenProperties;
import com.mask.token.security.MaskTokenSecurityConfig;
import com.mask.token.security.filter.MaskTokenAuthenticationFilter;
import com.mask.token.security.handler.MaskAuthenticationEntryPoint;
import com.mask.token.security.handler.MaskAccessDeniedHandler;
import com.mask.token.service.MaskTokenKeyService;
import com.mask.token.service.MaskTokenService;
import com.mask.token.service.MaskTokenRedisService;
import com.mask.token.service.MaskUserDetailsService;
import com.mask.token.util.MaskTokenParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * Mask Token 自动配置类
 *
 * @author mask
 * @since 1.0.0
 */
@Configuration
@ConditionalOnClass(MaskTokenService.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableConfigurationProperties(MaskTokenProperties.class)
@Import({
    MaskTokenSecurityConfig.class
})
public class MaskTokenAutoConfiguration {

    /**
     * 配置Redis Token服务
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate")
    public MaskTokenRedisService maskTokenRedisService(org.springframework.data.redis.core.RedisTemplate<String, String> redisTemplate, ObjectMapper objectMapper) {
        return new MaskTokenRedisService(redisTemplate, objectMapper);
    }

    /**
     * 配置密钥管理服务
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "mask.token.key-management.enabled", havingValue = "true", matchIfMissing = true)
    public MaskTokenKeyService maskTokenKeyService(MaskTokenProperties properties) {
        return new MaskTokenKeyService(properties);
    }

    /**
     * 配置Token服务
     */
    @Bean
    @ConditionalOnMissingBean
    public MaskTokenService maskTokenService(MaskTokenProperties properties, 
                                           @org.springframework.beans.factory.annotation.Autowired(required = false) MaskTokenRedisService redisService,
                                           @org.springframework.beans.factory.annotation.Autowired(required = false) MaskTokenKeyService keyService) {
        return new MaskTokenService(properties, redisService, keyService);
    }

    /**
     * 配置Token解析工具类
     */
    @Bean
    @ConditionalOnMissingBean
    public MaskTokenParser maskTokenParser(MaskTokenService tokenService) {
        return new MaskTokenParser(tokenService);
    }

    /**
     * 配置用户详情服务
     */
    @Bean
    @ConditionalOnMissingBean(UserDetailsService.class)
    public UserDetailsService userDetailsService() {
        return new MaskUserDetailsService();
    }

    /**
     * 配置Token认证过滤器
     */
    @Bean
    @ConditionalOnMissingBean
    public MaskTokenAuthenticationFilter maskTokenAuthenticationFilter(
            MaskTokenService tokenService, UserDetailsService userDetailsService) {
        return new MaskTokenAuthenticationFilter(tokenService, userDetailsService);
    }

    /**
     * 配置认证入口点处理器
     */
    @Bean
    @ConditionalOnMissingBean
    public MaskAuthenticationEntryPoint maskAuthenticationEntryPoint(ObjectMapper objectMapper) {
        return new MaskAuthenticationEntryPoint(objectMapper);
    }

    /**
     * 配置访问拒绝处理器
     */
    @Bean
    @ConditionalOnMissingBean
    public MaskAccessDeniedHandler maskAccessDeniedHandler(ObjectMapper objectMapper) {
        return new MaskAccessDeniedHandler(objectMapper);
    }

    /**
     * 配置ObjectMapper（如果不存在）
     */
    @Bean
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册JavaTime模块以支持Instant等时间类型
        objectMapper.registerModule(new JavaTimeModule());
        return objectMapper;
    }

    /**
     * 配置默认的CORS配置源（如果不存在）
     * 为其他包提供默认的corsConfigurationSource Bean
     */
    @Bean("corsConfigurationSource")
    @ConditionalOnMissingBean(name = "corsConfigurationSource")
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 使用兼容的方法设置允许的源
        configuration.setAllowedOrigins(java.util.Arrays.asList("*"));
        configuration.setAllowedMethods(java.util.Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(java.util.Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
